/*
 *  JDiv - API for Multimedia Application
 *  http://jdiv.sourceforge.net 
 *  ------------------------------------
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

package com.jdiv.physics;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Joint;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJoint;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
import com.jdiv.Const;
import com.jdiv.kernel.JDivSystem;

/** Revolute joint. This requires defining an anchor point where the bodies are joined. The definition uses local anchor points so that the initial configuration can violate the constraint slightly. You also need to specify the initial relative angle for joint limits. This helps when saving and loading a game. The local anchor points are measured from the body's origin rather than the center of mass because: 1. you might not know where the center of mass will be. 2. if you add/remove shapes from a body and recompute the mass, the joints will be broken.  */

public class JointRevolute {
	
	RevoluteJointDef jointDef;
	Joint joint;
	
	/**
	 * Constructor of JointRevolute.
	 * @param bodyA Body of object A.
	 * @param bodyB Body of object B.
	 * @param collideConnected Sets if they collide with each other.
	 */
	 
	public JointRevolute( Body bodyA, Body bodyB, boolean collideConnected ){
		
	 jointDef = new RevoluteJointDef();
	 
	 joint = null;
	 
	 init( bodyA, bodyB, collideConnected );
	}
	
	/**
	 * Initialize the bodies.
	 * @param bodyA Body of object A.
	 * @param bodyB Body of object B.
	 * @param collideConnected Sets if they collide with each other.
	 */
	
   public void init ( Body bodyA, Body bodyB, boolean collideConnected ){
		
		if( joint != null ) return;
		
		jointDef.bodyA = bodyA;
		jointDef.bodyB = bodyB;
		jointDef.collideConnected = collideConnected;
	}
   
   /**
    * Sets the pivot point from object A.
    * @param x Coordinate X.
    * @param y Coordinate Y.
    */
	 
	public void setAnchorA( float x, float y ){
	 jointDef.localAnchorA.set(x * Const.BOX2D_SCREEN_TO_PHYSICS, 
			                   y * Const.BOX2D_SCREEN_TO_PHYSICS);
	}
	
	/**
	    * Sets the pivot point from object B.
	    * @param x Coordinate X.
	    * @param y Coordinate Y.
	    */
	 
	public void setAnchorB( float x, float y ){
	 jointDef.localAnchorB.set(x * Const.BOX2D_SCREEN_TO_PHYSICS, 
			                   y * Const.BOX2D_SCREEN_TO_PHYSICS);
	}
	
	/**
	 * Enable joint limits.
	 * @param min The lower angle for the joint limit.
	 * @param max The upper angle for the joint limit.
	 */
	 
	public void setAngleLimit( float min, float max ){
	 jointDef.enableLimit = true;
	 jointDef.lowerAngle  = min * MathUtils.degreesToRadians;
	 jointDef.upperAngle  = max * MathUtils.degreesToRadians;
	}
	
	/**
	 * Enable the joint motor.
	 * @param maxMotorTorque The maximum motor torque, usually in N-m. 
	 * @param speed The desired motor speed in angle per second. 
	 */
	 
	public void setMotor( float maxMotorTorque, float speed ){
	 jointDef.enableMotor    = true;
	 jointDef.maxMotorTorque = maxMotorTorque;
	 jointDef.motorSpeed     = speed * MathUtils.degreesToRadians;
	}
	
	/**
	 * Add the joint to the physical world.
	 * @return The joint in the physical world.
	 */
	 
	public Joint addToWorld(){
	 if( joint != null ) return joint;
	 
	 if( JDivSystem.box2dWorld != null )	
	  joint = JDivSystem.box2dWorld.createJoint(jointDef);
	 
	 return joint;
	}
	
	/**
	 * @return Gets RevoluteJoint of LibGdx.
	 */
	
	public RevoluteJoint getRevoluteJoint(){
		return (RevoluteJoint)joint;
	}
	
	/** Delete the joint in the physical world. */
	
	public void delete(){
		if( (JDivSystem.box2dWorld == null) || (joint == null) ) return;
		
		JDivSystem.box2dWorld.destroyJoint(joint);
		joint = null;
	}
}
